package com.example.teaching_server.controller;

import com.example.teaching_server.common.ApiResponse;
import com.example.teaching_server.dto.RescheduleRequest;
import com.example.teaching_server.dto.ScheduleDTO;
import com.example.teaching_server.entity.ScheduleEntity;
import com.example.teaching_server.repository.ScheduleRepository;
import com.example.teaching_server.service.ScheduleService;
import com.example.teaching_server.dto.CreateActivityRequest;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDate;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/api/schedules")
@RequiredArgsConstructor
@Tag(name = "课程表管理", description = "课程表查询和管理接口")
public class ScheduleController {
    private final ScheduleService scheduleService;
    private final ScheduleRepository scheduleRepository;

    /**
     * 获取教师课程表
     */
    @GetMapping
    @Operation(summary = "获取教师课程表", description = "根据教师ID、班级ID和日期范围获取课程表")
    public ApiResponse<List<ScheduleDTO>> getTeacherClassScheduleByDateRange(
            @Parameter(description = "教师ID") @RequestParam Long teacherId,
            @Parameter(description = "班级ID") @RequestParam Long classId,
            @Parameter(description = "开始日期") @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @Parameter(description = "结束日期") @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {

        log.info("开始获取教师课程表: teacherId={}, classId={}, startDate={}, endDate={}",
                teacherId, classId, startDate, endDate);

        try {
            List<ScheduleDTO> schedules = scheduleService.getTeacherClassScheduleByDateRange(
                    teacherId, classId, startDate, endDate);
            log.info("成功获取教师{}课程表，共{}条记录", teacherId, schedules.size());
            return ApiResponse.success("课程表获取成功", schedules);
        } catch (Exception e) {
            log.error("获取教师课程表失败: teacherId={}, classId={}", teacherId, classId, e);
            return ApiResponse.fail("课程表获取失败: " + e.getMessage());
        }
    }

    /**
     * 获取课程选项
     */
    @GetMapping("/options")
    @Operation(summary = "获取课程选项", description = "根据教师ID或班级ID获取课程选项列表")
    public ApiResponse<List<ScheduleOptionDTO>> getScheduleOptions(
            @Parameter(description = "教师ID") @RequestParam(required = false) Long teacherId,
            @Parameter(description = "班级ID") @RequestParam(required = false) Long classId) {

        log.info("开始获取课程选项: teacherId={}, classId={}", teacherId, classId);

        try {
            List<ScheduleEntity> schedules;

            if (teacherId != null) {
                schedules = scheduleRepository.findByTeacherTeacherId(teacherId);
            } else if (classId != null) {
                schedules = scheduleRepository.findByClassEntityId(classId);
            } else {
                schedules = scheduleRepository.findAll();
            }

            List<ScheduleOptionDTO> options = schedules.stream()
                    .map(this::convertToOptionDTO)
                    .collect(Collectors.toList());

            log.info("成功获取{}个课程选项", options.size());
            return ApiResponse.success("课程选项获取成功", options);
        } catch (Exception e) {
            log.error("获取课程选项失败: teacherId={}, classId={}", teacherId, classId, e);
            return ApiResponse.fail("获取课程选项失败: " + e.getMessage());
        }
    }

    /**
     * 获取学生课程表
     */
    @GetMapping("/student")
    @Operation(summary = "获取学生课程表", description = "根据班级ID和日期范围获取学生课程表")
    public ApiResponse<List<ScheduleDTO>> getStudentScheduleByDateRange(
            @Parameter(description = "学生ID") @RequestParam(required = false) Long studentId,
            @Parameter(description = "班级ID") @RequestParam Long classId,
            @Parameter(description = "开始日期") @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @Parameter(description = "结束日期") @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {

        log.info("开始获取学生课程表: studentId={}, classId={}, startDate={}, endDate={}",
                studentId, classId, startDate, endDate);

        try {
            List<ScheduleDTO> schedules = scheduleService.getClassScheduleByDateRange(
                    classId, startDate, endDate);
            log.info("成功获取班级{}课程表，共{}条记录", classId, schedules.size());
            return ApiResponse.success("学生课程表获取成功", schedules);
        } catch (Exception e) {
            log.error("获取学生课程表失败: classId={}", classId, e);
            return ApiResponse.fail("学生课程表获取失败: " + e.getMessage());
        }
    }

    /**
     * 调整课程时间
     */
    @PostMapping("/{scheduleId}/reschedule")
    @Operation(summary = "调整课程时间", description = "调整指定课程的时间安排")
    public ApiResponse<?> reschedule(
            @Parameter(description = "课程ID") @PathVariable Long scheduleId,
            @RequestBody RescheduleRequest request) {

        log.info("开始调整课程时间: scheduleId={}, specificDate={}, timeSlotId={}",
                scheduleId, request.getSpecificDate(), request.getTimeSlotId());

        try {
            scheduleService.rescheduleWithTimeSlot(scheduleId, request.getSpecificDate(), request.getTimeSlotId());
            log.info("课程时间调整成功: scheduleId={}", scheduleId);
            return ApiResponse.success("课程时间调整成功");
        } catch (Exception e) {
            log.error("调整课程时间失败: scheduleId={}", scheduleId, e);
            return ApiResponse.fail("调整失败: " + e.getMessage());
        }
    }

    /**
     * 创建活动
     */
    @PostMapping("/activities")
    @Operation(summary = "创建活动", description = "创建新的活动安排")
    public ApiResponse<?> createActivity(@RequestBody CreateActivityRequest request) {

        log.info("开始创建活动: activityName={}", request.getActivityName());

        try {
            ScheduleDTO createdActivity = scheduleService.createActivity(request);
            log.info("活动创建成功: activityId={}", createdActivity.getScheduleId());
            return ApiResponse.success("活动创建成功", createdActivity);
        } catch (Exception e) {
            log.error("创建活动失败", e);
            return ApiResponse.fail("活动创建失败: " + e.getMessage());
        }
    }

    /**
     * 转换Entity到选项DTO
     */
    private ScheduleOptionDTO convertToOptionDTO(ScheduleEntity schedule) {
        ScheduleOptionDTO option = new ScheduleOptionDTO();
        option.setScheduleId(schedule.getScheduleId());
        option.setDisplayName(schedule.getDisplayName() != null ?
                schedule.getDisplayName() : generateDisplayName(schedule));
        return option;
    }

    /**
     * 生成显示名称
     */
    private String generateDisplayName(ScheduleEntity schedule) {
        StringBuilder displayName = new StringBuilder();

        if (schedule.getClassEntity() != null && schedule.getClassEntity().getClassName() != null) {
            displayName.append(schedule.getClassEntity().getClassName());
        }

        if (schedule.getCourse() != null && schedule.getCourse().getCourseName() != null) {
            displayName.append("-").append(schedule.getCourse().getCourseName());
        }

        if (schedule.getTimeSlot() != null) {
            displayName.append("-").append(schedule.getTimeSlot().getStartTime())
                    .append("-").append(schedule.getTimeSlot().getEndTime());
        }

        return displayName.toString();
    }

    /**
     * 课程选项DTO
     */
    @Setter
    @Getter
    public static class ScheduleOptionDTO {
        private Long scheduleId;
        private String displayName;

    }
}
